package com.example.lucene.service;

import com.example.lucene.IndexManager;
import com.example.lucene.dao.knowledgeBaseDao;
import com.example.lucene.model.KnowledgeBase;
import com.example.lucene.model.ProductCategory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @Author yanggld
 * @Date 2019/5/24-16:28
 * @Description
 */
@Service
public class KnowledgeBaseService {

	@Autowired
	private knowledgeBaseDao knowledgeBaseDao;

	@Value("${KB_LuceneIndex}")
	private String KB_LuceneIndex;

	//ProductCode字典
	private Map<String, ProductCategory> productCodeMap;

	public boolean createIndex(String[] products, String mode) {
		Map<String, ProductCategory> allProductMap = getProductCodeMap();
		Collection<ProductCategory> createProducts = new ArrayList<>(products.length);
		for (String product:products) {
			if(product == null || product.isEmpty() || !allProductMap.containsKey(product)){
				System.out.println("Can't found product code " + product + " create index fail!");
				continue;
			}
			createProducts.add(allProductMap.get(product));
		}
		return AsynCreateIndex(createProducts, mode);
	}

	public Map<String, ProductCategory> getProductCodeMap() {
		if (this.productCodeMap == null) {
			//初始化分类
			Map<String, ProductCategory> productCodeMap = new HashMap<String, ProductCategory>();
			//获取数据库产品
			List<ProductCategory> products = knowledgeBaseDao.getIndexProduct();
			for (ProductCategory product : products) {
				//重新指定索引目录相对路径
				product.setProductPath(KB_LuceneIndex + product.getProductPath());
				productCodeMap.put(product.getProductCode(), product);
			}
			this.productCodeMap = productCodeMap;
			return productCodeMap;
		}
		return this.productCodeMap;
	}

	private boolean AsynCreateIndex(Collection<ProductCategory> productCategories, String mode){
		boolean isSuccess = true;
		//索引处理任务
		class CreateIndexTask implements Callable<Boolean> {
			ProductCategory productCategory;
			String mode;
			CreateIndexTask(ProductCategory productCategory, String mode) {
				this.productCategory = productCategory;
				this.mode = mode;
			}

			@Override
			public Boolean call() throws Exception {
				try {
					return createIndexCore(productCategory, mode);
				} catch (Exception ex) {
					System.out.println("CreateIndex All in product:" + productCategory.getProductCode() + " fail!");
					ex.printStackTrace();
				}
				return false;
			}
		}
		//固定大小的线程池
		//Executors.newFixedThreadPool(6);
		//可变大小的线程池
		ExecutorService es = Executors.newCachedThreadPool();
		List<Callable<Boolean>> todo = new ArrayList<>(productCategories.size());
		//逐一创建索引处理任务
		for (ProductCategory product : productCategories) {
			if(product == null){
				continue;
			}
			todo.add(new CreateIndexTask(product, mode));
		}
		try{
			//批量执行，并等待其全部执行完毕
			List<Future<Boolean>> answers = es.invokeAll(todo);
			for (Future<Boolean> future : answers) {
				Boolean result = future.get();
				if(result == null || !result.booleanValue()){
					isSuccess = false;
				}
			}
		}catch (Exception ex){
			ex.printStackTrace();
		}
		return isSuccess;
	}


	private boolean createIndexCore(ProductCategory productCategory, String mode){
		String category = productCategory.getProductCategory();
		System.out.println("CreateIndex query category: " + category);
		List<KnowledgeBase> knowledgeBases = getKnowledgeBaseList(productCategory.getProductCode(), mode);
		int size;
		if (knowledgeBases == null || (size = knowledgeBases.size()) <= 0) {
			System.out.println("CreateIndex " + category + " stop because KnowledgeBase count is null or zero.");
			return true;
		} else {
			System.out.println("CreateIndex query category: " + category + " a total of " + size + " mode : " + mode);
		}
		boolean result = IndexManager.createIndex(productCategory.getProductPath(), knowledgeBases, mode);
		if(result){
			System.out.println("CreateIndex category: " + category + " success!");
			//生成索引成功之后更新知识库的ValidCode从0变成1
			knowledgeBaseDao.validKnowledgeBase(knowledgeBases);
		} else{
			System.out.println("CreateIndex category: " + category + " fail!");
		}
		return  result;
	}


	private List<KnowledgeBase> getKnowledgeBaseList(String productCode, String mode) {
		java.util.Date date = new java.util.Date();
		Timestamp time = new Timestamp(date.getTime());
		return knowledgeBaseDao.getKnowledgeBase(productCode, mode, time);
	}

}
